package com.conan.app.dailyflickr.app;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.conan.app.dailyflickr.App;
import com.conan.app.dailyflickr.AppData;
import com.conan.app.dailyflickr.utils.PrefUtils;

public class DailyPhotoData {
    public static final String TAG = "PhotoDailyInfo";

    static final public int MAX_PAGE = 33;
    static final public int PER_PAGE = 15;
    static final public int PAGES_NUMBER = 1;

    private static final String RESPONSE_TAG_PHOTOS = "photos";
    private static final String RESPONSE_ATTR_PAGES = "pages";
    private static final String RESPONSE_ATTR_PAGE = "page";

    public static final String RESPONSE_TAG_PHOTO = "photo";
    public static final String RESPONSE_ATTR_ID = "id";
    public static final String RESPONSE_ATTR_SECRET = "secret";
    public static final String RESPONSE_ATTR_SERVER = "server";
    public static final String RESPONSE_ATTR_FARM = "farm";
    public static final String RESPONSE_ATTR_TITLE = "title";
    public static final String RESPONSE_ATTR_DATE_TAKEN = "datetaken"; 
    public static final String RESPONSE_TAG_STATE = "stat";
    public static final String RESPONSE_ATTR_STATE_OK = "ok";
    public static final String RESPONSE_TAG_MESSAGE = "message";
    public static final String RESPONSE_LATITUDE = "latitude";
    public static final String RESPONSE_LONGTITUDE = "longitude";
    
    private FlickrApiHelper mFlickrApi;

    private PhotoList mPhotoList;

    public DailyPhotoData(Context context) {
        mFlickrApi = FlickrApiHelper.getInstance();

        mPhotoList = new PhotoList();
        // the first time get data
        // updateDataFromFlickr(0);
    }

    private JSONObject getLocalData(Date date){
        long current = PrefUtils.getLongPref(App.getContext(), AppData.PREF_DAILY, AppData.PREF_CURRENT, 0);
        if(current == 0) return null;
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(current);
        if(cal.get(Calendar.DATE) == date.getDate() &&
                cal.get(Calendar.MONTH) == date.getMonth() &&
                cal.get(Calendar.YEAR) == (date.getYear() + 1900)){
            String data = PrefUtils.getStringPref(App.getContext(), AppData.PREF_DAILY, AppData.PREF_DATA, null);
            try {
                return new JSONObject(data);
            } catch (JSONException e) {
                Log.e(TAG, "[getLocalData] load local photo failed caused JSONException.");// e.printStackTrace();
                return null;
            }
        }
        
        return null;
    }
    
    /**
     * api_key (Required)
		    Your API application key. See here for more details.
		date (Optional)
		    A specific date, formatted as YYYY-MM-DD, to return interesting photos for.
		extras (Optional)
		    A comma-delimited list of extra information to fetch for each returned record. Currently supported fields are: description, license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_m, url_z, url_l, url_o
		per_page (Optional)
		    Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.
		page (Optional)
		    The page of results to return. If this argument is omitted, it defaults to 1. 
     */
    public boolean updateDataFromFlickr(int page, int perPage, Date date){
        JSONObject jSONObject = getLocalData(date);
        Log.e("mapp", "--------------------");
        Log.d("mapp", jSONObject == null ? "null" : "getLocalData(date) == true");
        Log.e("mapp", "--------------------");
        if(jSONObject == null){
            try {
                jSONObject = mFlickrApi.flickrPhotoApiHttp(1, AppData.PERPAGE/*perPage*/, date);
                if(jSONObject == null) return false;
                String message = "fail";
                message = jSONObject.getString(RESPONSE_TAG_STATE);
                if(RESPONSE_ATTR_STATE_OK.compareTo(message) != 0) {
                    return false;
                }
            } catch (IOException e) {
                Log.e(TAG, "[updateDataFromFlickr] load photo data failed caused IOException");
                return false;
            } catch (JSONException e) {
                Log.e(TAG, "[updateDataFromFlickr] load photo data failed caused JSONException");
                return false;
            }
            // save pref
            PrefUtils.putStringPref(App.getContext(), AppData.PREF_DAILY, AppData.PREF_DATA, jSONObject.toString());
            PrefUtils.putLongPref(App.getContext(), AppData.PREF_DAILY, AppData.PREF_CURRENT, date.getTime());
        }
        
        parsePhotos(jSONObject, mPhotoList, page, perPage);
        return true;
    }

    public PhotoList getPhotoList(){
        return mPhotoList;
    }

    /**
     * @author @le.nguyen
     *  @param @param jSonParser
     *  @param @param photos
     *  @param @return
     *  @see 
     *  <photos page="2" pages="89" perpage="10" total="881">
     *			<photo id="2636" owner="47058503995@N01" 
     *					secret="a123456" server="2" title="test_04"
     *					ispublic="1" isfriend="0" isfamily="0" />
     *	<photos>
     */
    private int parsePhotos(JSONObject jSonParser, PhotoList photos, int page, int perpage){
        //jSonParser.
        if(jSonParser == null) return 0;

        //inner Json object
        JSONObject jSONObjectInner;
        try {
            jSONObjectInner = jSonParser.getJSONObject(RESPONSE_TAG_PHOTOS);
            Log.e("mapp", jSONObjectInner.toString());
            photos._pages =  jSONObjectInner.getInt(RESPONSE_ATTR_PAGES); 
            photos.current_page = 	jSONObjectInner.getInt(RESPONSE_ATTR_PAGE);
            // inner array of photos
            JSONArray photoArray = jSONObjectInner.getJSONArray(RESPONSE_TAG_PHOTO); 
            Log.e("mapp", "photoArray = " + photoArray.length());
            //get one random photo from array
            SimpleDateFormat parseFormat = null;
            SimpleDateFormat outputFormat = null;
            // int total = photoArray.length();
            photos.clear();
            int start = page * perpage;
            for(int i= start; i < start + perpage; i++){
                JSONObject jSONPhoto = photoArray.getJSONObject(i);

                final Photo photo = new Photo();
                photo.setUrl(jSONPhoto.getString(RESPONSE_ATTR_FARM),
                        jSONPhoto.getString(RESPONSE_ATTR_SERVER), 
                        jSONPhoto.getString(RESPONSE_ATTR_ID),
                        jSONPhoto.getString(RESPONSE_ATTR_SECRET));
                photo.mTitle = jSONPhoto.getString(RESPONSE_ATTR_TITLE);
                photo.mDate = jSONPhoto.getString(RESPONSE_ATTR_DATE_TAKEN);
                photo.mID = jSONPhoto.getString(RESPONSE_ATTR_ID);
                photo.latitude = jSONPhoto.getLong(RESPONSE_LATITUDE);
                photo.longtitude = jSONPhoto.getLong(RESPONSE_LONGTITUDE);
                
                if (parseFormat == null) {
                    parseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    outputFormat = new SimpleDateFormat("MMMM d, yyyy");
                }

                try {
                    photo.mDate = outputFormat.format(parseFormat.parse(photo.mDate));
                } catch (java.text.ParseException e) {
                    Log.w(TAG, "Could not parse photo date", e);
                }

                photos.add(photo);
            }
            // Log.w(TAG, "[parse photo][done] = " + photos.getCount());;
        } catch (JSONException e) {
            e.printStackTrace();
        } 

        return photos.getCount();
    }

    /********************************************************************************
     ****************		PhotoList	********************************************
     * A list of {@link com.google.android.photostream.Flickr.Photo photos}.
     * The page index and the page count both depend on the number of photos per page.
     */

    public static class PhotoList{
        private ArrayList<Photo> mPhotos = new ArrayList<Photo>();
        public int _id;
        public int _pages = 33;
        public int current_page = 1;
        public void add(Photo photo){
            mPhotos.add(photo);
        }

        public void clear(){
            mPhotos.clear();
        }

        public Photo remove(int index){
            return mPhotos.remove(index);
        }

        public Photo get(int index){
            if(index < mPhotos.size()){
                return mPhotos.get(index);
            }
            return null;
        }

        public int getCount(){
            return mPhotos.size();
        }
    }

    /*********************************************************************************
     * ***************		Photo			******************************************
     * A photo is represented by a title, the date at which it was taken and a URL.
     * The URL depends on the desired {@link com.google.android.photostream.Flickr.PhotoSize}.
     */
    private static final String PHOTO_IMAGE_URL = "%s%s.jpg";
    private static final String PHOTO_PATTERN_URL = "http://farm%s.static.flickr.com/%s/%s_%s";
    public static class Photo implements Parcelable{
        public String mID;
        public String mUrl;
        public String mTitle;
        private String mDate;
        public boolean loaded = false;
        public long latitude;
        public long longtitude;
        
        public Photo() {
        }

        public Photo(String id, String url, String title){
            mID = id;
            mUrl = url;
            mTitle = title;
        }

        public Photo(Parcel in) {
            mID = in.readString();
            mUrl = in.readString();
            mTitle = in.readString();
            mDate = in.readString();
            latitude = in.readLong();
            longtitude = in.readLong();
        }

        public String getID(){
            return mID;
        }

        public void setUrl(String farm, String server, String id, String secret){
            mUrl = String.format(PHOTO_PATTERN_URL, farm, server, id, secret);
        }
        
        public String getTitle(){
            return mTitle;
        }

        public String getDate(){
            return mDate;
        }

        /**
         * @see com.google.android.photostream.Flickr.PhotoSize
         * "http://farm%s.static.flickr.com/%s/%s_%s%s.jpg";
         */
        public String getUrl(PhotoSize photoSize) {
            return String.format(PHOTO_IMAGE_URL, mUrl, photoSize.size());
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public String toString() {
            return mTitle + ", " + mDate + " @" + mUrl;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(mID);
            dest.writeString(mUrl);
            dest.writeString(mTitle);
            dest.writeString(mDate);
            dest.writeLong(latitude);
            dest.writeLong(longtitude);
        }

        public static final Parcelable.Creator<Photo> CREATOR = new Parcelable.Creator<Photo>() {

            public Photo createFromParcel(Parcel in){
                return new Photo(in);
            }

            public Photo[] newArray(int size){
                return new Photo[size];
            }
        };
    }

    public enum PhotoSize {
        /** Small square image (75x75 px).  */
        SMALL_SQUARE("_s", 75),

        /** Thumbnail image (the longest side measures 100 px).	*/
        THUMBNAIL("_t", 100),

        /** Small image (the longest side measures 240 px).	*/
        SMALL("_m", 240),

        /** Medium image (the longest side measures 500 px).	*/
        MEDIUM("", 500),

        /** Large image (the longest side measures 1024 px).    */
        LARGE("_b", 1024);

        private final String mSize;
        private final int mLongSide;

        private PhotoSize(String size, int longSide) {
            mSize = size;
            mLongSide = longSide;
        }

        /**
         * Returns the size in pixels of the longest side of the image.
         * @return the dimension in pixels of the longest side.
         */
        int longSide() {
            return mLongSide;
        }

        /**
         * Returns the name of the size, as defined by Flickr. For instance,
         * the LARGE size is defined by the String "_b".
         * @return
         */
        String size() {
            return mSize;
        }

        @Override
        public String toString() {
            return name() + ", longSide=" + mLongSide;
        }
    }
}
